package com.codetile.batch.execution;

import com.codetile.batch.db.User;
import org.springframework.batch.core.*;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor;
import org.springframework.batch.core.converter.DefaultJobParametersConverter;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.JobOperator;
import org.springframework.batch.core.launch.support.SimpleJobOperator;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemStreamReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableBatchProcessing
public class FileRestarDemo implements StepExecutionListener, ApplicationContextAware {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    @Qualifier("dbJdbcWrite")
    private ItemWriter<User> dbWrite;

    @Autowired
    @Qualifier("streamReader")
    private ItemReader<User> fileItemWrite;

    @Autowired
    private MySkipListener mySkipListener;

    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    private JobRepository jobRepository;

    @Autowired
    private JobExplorer jobExplorer;

    @Autowired
    private JobRegistry jobRegistry;

    private ApplicationContext context;

    @Bean
    public Job restartJob(){
        return jobBuilderFactory.get("restartJob")
                .start(restartStep())
                .build();
    }

    @Bean
    public Step restartStep(){
        return stepBuilderFactory.get("restartStep")
                .<User,User>chunk(2)
                .reader(fileItemWrite)
                .writer(dbWrite)
                //容错
                .faultTolerant()
//                //重试
//                .retry(CustomRetryException.class)
//                //重试次数，reader、processor、writer出错总次数。
//                .retryLimit(5)
                //跳过
                .skip(CustomRetryException.class)
                //跳过次数，reader、processor、writer出错总次数。
                .skipLimit(5)
                //错误跳过监听器
                .listener(mySkipListener)
                .build();
    }

    /**
     * 错误重试
     */
//        .faultTolerant()
//        .retry(CustomRetryException.class)
//        .retryLimit(5)

    /**
     * 错误跳过
     */
//    .faultTolerant()
//    .skip(CustomRetryException.class)
//    .skipLimit(5)


    @Bean
    public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor() throws Exception {
        JobRegistryBeanPostProcessor postProcessor=new JobRegistryBeanPostProcessor();

        postProcessor.setJobRegistry(jobRegistry);
        postProcessor.setBeanFactory(context.getAutowireCapableBeanFactory());
        postProcessor.afterPropertiesSet();
        return  postProcessor;
    }


    @Bean
    public JobOperator jobOperator(){
        SimpleJobOperator operator=new SimpleJobOperator();
        operator.setJobLauncher(jobLauncher);
        operator.setJobParametersConverter(new DefaultJobParametersConverter());
        operator.setJobExplorer(jobExplorer);
        operator.setJobRepository(jobRepository);
        return operator;
    }


    @Override
    public void beforeStep(StepExecution stepExecution) {

    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        return null;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context=applicationContext;
    }
}
